package com.company.nuwa.common.handler;

import com.company.nuwa.common.domain.HttpMessageResult;
import com.company.nuwa.common.exception.BizException;
import com.company.nuwa.common.exception.FeignInvokeBizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;

import java.util.stream.Collectors;

/**
 * <p>异常处理</p>
 *
 * @author Lionel Lee
 * @version 1.0: AbstractGlobalExceptionHandler.java
 * @date 2022/8/25 17:35
 */
@Slf4j
public abstract class AbstractGlobalExceptionHandler implements ApplicationContextAware {

    private static final int INTERNAL_ERROR_CODE = 99999;

    private static final int ILLEGAL_ARGUMENT_CODE = 99001;

    private static final String DEFAULT_ERROR_MSG = "服务打瞌睡,请稍后再试!";

    private static final String PROD = "prod";

    private static final String PRE = "pre";

    private String environment;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        environment = applicationContext.getEnvironment().getActiveProfiles()[0];
    }

    public HttpMessageResult handle(Exception e) {
        String errorMsg = ExceptionUtils.getStackTrace(e);
        log.error("[应用异常信息:{}]", errorMsg);
        if (e instanceof BizException) {
            BizException exception = (BizException) e;
            return HttpMessageResult.failure(exception.getCode(), exception.getMessage());
        } else if (e instanceof FeignInvokeBizException) {
            FeignInvokeBizException exception = (FeignInvokeBizException) e;
            return HttpMessageResult.failure(exception.getCode(), exception.getMessage())
                    .setData(null);
        } else if (e instanceof MethodArgumentNotValidException) {
            // 参数校验
            MethodArgumentNotValidException exs = (MethodArgumentNotValidException) e;
            BindingResult bindingResult = exs.getBindingResult();
            errorMsg = bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage)
                    .collect(Collectors.toList()).toString();
            return HttpMessageResult.failure(ILLEGAL_ARGUMENT_CODE, errorMsg);
        }
        if (isPreOrProd()) {
            // 预发布和生产环境，友好提示
            return HttpMessageResult.failure(INTERNAL_ERROR_CODE, DEFAULT_ERROR_MSG);
        }
        return HttpMessageResult.failure(INTERNAL_ERROR_CODE, errorMsg);
    }

    private boolean isPreOrProd() {
        return StringUtils.equals(PROD, environment) || StringUtils.equals(PRE, environment);
    }

}
